home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 6 / QRZ Ham Radio Callsign Database - Volume 6.iso / mac / files / amiga / csrc720j.lzh / hamiga.c < prev    next >
C/C++ Source or Header  |  1993-02-16  |  20KB  |  789 lines

  1. /*
  2.  *  HAMIGA.C - 19th Aug 1988 - System dependent functions.
  3.  *  replacement for mbibm.c
  4.  *  Copyright 1990,1991 Pete Hardie VE5VA
  5.  *
  6.  */
  7.  
  8. #include "mb.h"
  9. #include <intuition/intuition.h>
  10. #include <intuition/intuitionbase.h>
  11. #include <graphics/text.h>
  12. #include <ctype.h>
  13. #include <time.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include "port.h"
  17.  
  18. extern struct Window *mywindow;
  19. struct IntuiMessage *NewMessage;
  20. short interflag = 0;
  21. short debug;
  22. char tmpstr[100];
  23. extern struct IOStdReq *Con_Read,*Con_Write;
  24. extern struct MsgPort *my_port;
  25. extern unsigned char rs_in[2];
  26. extern unsigned char rs_out[2];
  27. extern char optflags[];
  28.  
  29. char l_date[7], l_time[5];
  30. char pt_flag = 0;
  31. short done_flag = 1;
  32.  
  33. short tapr_flag = 0;
  34. struct regd *CURBUF = 0L;
  35. unsigned char *B_FROM = 0,*B_TO = 0;
  36.  
  37. char z_date[7], z_time[5];
  38. /*
  39.  *  Set the current I/O device.
  40.  */
  41.  
  42. ioport(pp)
  43. PORTS *pp;
  44. {
  45.   port = pp;
  46. }
  47.  
  48. /*
  49.  *  Return non-zero if a character waits at current input.
  50.  */
  51. instat()
  52. {
  53.   register int st;
  54.  
  55.    if (port->dev is p_console) {
  56.       /* check for char at console */
  57.       if(CheckIO((struct IORequest *)Con_Read))return(1);
  58.       else return(0);
  59.    }
  60.    if(port->dev is p_tnc) {
  61.       /* check for char at serial port */
  62.       if(CheckIO((struct IORequest *)my_port)) {
  63.          if(optflags[4])interflag = 1;
  64.          return(1);
  65.       }
  66.       else return(0);
  67.    }
  68.    return(0);
  69. }
  70. /* output char to serial port */
  71. outi(ch)
  72. char ch;
  73. {
  74.    schar(ch);
  75. }
  76.  
  77. /*
  78.  *  Put the character out the current port,
  79.  *  echo to console if the current port is not the console.
  80.  *  Note special handling of end-of-line character.
  81.  */
  82.  
  83. outchar(ch)
  84. char ch;
  85. {
  86.    if (ch is '\r') return;
  87.    if (ch is '\n') ch = '\r';
  88. /*
  89.  *  Put it out to the console, if it is going there.
  90.  */
  91.  
  92.    if ((port->dev is p_console) or port->ec)   {
  93.       if (ch is '\r') ttputc('\n');/* output '\n' */;
  94.       ttputc(ch);
  95.    }
  96.  
  97. /*
  98.  *  If the port is the console, nothing more to do.
  99.  */
  100.  
  101.    if (port->dev is p_console) return;
  102.  
  103. /*
  104.  *  Stuff this byte out the port.
  105.  */
  106.  
  107.    outi(ch);
  108.    if (ch is '\r')
  109.       if (port->flags & p_lf) outi('\n');
  110. }
  111. #define PROCLEN 100
  112. /* This can't use tmpstr because some of the routines call this with
  113.    tmpstr as the argument
  114. */
  115. unsigned char procstr[PROCLEN];
  116. unsigned char procstr1[PROCLEN];
  117.  
  118. outstr(cp)
  119. unsigned char *cp;
  120. {
  121.    register unsigned char *p,*q;
  122.    register int beepcount,i;
  123.    /* count the number of beeps in the line so that we can give an audible
  124.       as well as visual beep
  125.    */
  126.    beepcount = 0;
  127.    if((port->dev is p_console) || port->ec) {
  128.       for(q = cp,p = &procstr[0];*q && p < &procstr[PROCLEN-1];q++) {
  129.          if(*q is '\r')continue;
  130.          *p++ = *q;
  131.          if(*q == '\007')beepcount++;
  132.       }
  133.       *p = 0;
  134.       Con_Write->io_Data = (APTR) &procstr[0];
  135.       Con_Write->io_Length = p-&procstr[0];
  136.       Con_Write->io_Command = CMD_WRITE;
  137.       DoIO((struct IORequest *)Con_Write);
  138.       while(beepcount--) {
  139.          beep();
  140.          Delay(15L);
  141.       }
  142.    }
  143.    if(port->dev is p_console)return;
  144.    for(q = cp,p = &procstr1[0];*q && (p < &procstr1[PROCLEN-1]);q++) {
  145.       if(*q is '\r')continue;
  146.       if(*q == '\n')*p++ = '\r';
  147.       else          *p++ = *q;
  148.    }
  149.    *p = 0;
  150.    senddata(&procstr1[0]);
  151. }
  152.  
  153. hex(c)
  154. char c;
  155. {
  156.    char k;
  157.    k = c;
  158.    if((k >= '0') && (k <= '9'))return(k - '0');
  159.    k = toupper(k);
  160.    if((k >= 'A') && (k <= 'F'))return(k - 'A' + 10);
  161.    return(0);
  162. }
  163. flipdebug()
  164. {
  165.    debug ^= 1;
  166.    if(debug) {
  167.       ttputs("debug now ON\n");
  168.    }
  169.    else {
  170.       ttputs("debug now OFF\n");
  171.    }
  172. }
  173. extern unsigned char ichar;
  174. extern long keybit,windbit,portbit,timerbit;
  175. long getbits;
  176. struct timeRequest {
  177.    struct IORequest tr_node;
  178.    struct timeval tr_time;
  179. };
  180. extern struct timeRequest timermsg;
  181.  
  182. /* replace the original do_idle because it busy-waited ...
  183.    this version sleeps until there is something to do
  184. */
  185. PORTS *devtnc;
  186. extern short cursecs;
  187. do_idle()
  188. {
  189.    register unsigned char ch,*cp;
  190.    register PORTS *p;
  191.    register struct regd *rp;
  192.    int curmin,curmon;
  193.    ULONG class,waitbits;
  194.    USHORT code;
  195.  
  196.    devtnc = NULL;
  197.    cursor_off();
  198.    devtnc = 0;
  199.    for(p=porthd; p != NULL; p = p->next) {
  200.       p->ec = p->ecmon;
  201.       if((devtnc == 0) && (p->id != 'Z'))devtnc = p;
  202.    }
  203.    if(devtnc == 0) {
  204.       ttputs("Can't find port\n");
  205.       setbusy();
  206.       done(1);
  207.    }
  208.    ioport(devtnc);
  209.    allon();
  210.    cp = (unsigned char *) devtnc->line;
  211.    /* figure out time to next forward and set timer */
  212.    curtim();
  213.    curmin = 60 - cursecs;
  214.    settimer(curmin);
  215.    /* There might already be an unread char at the serial or console port */
  216.    waitbits = windbit | portbit | timerbit | keybit;
  217.    clrbusy();
  218. ttputs("\nIDLE\n");
  219.    if(cpyline(0))goto logit;
  220.    while(1)  {
  221.       if(CURBUF = (struct regd *)GetMsg(my_port)) goto port_loop;
  222.       getbits = Wait(waitbits);
  223.       if(windbit & getbits) {
  224.          while(NewMessage = (struct IntuiMessage *)
  225.                       GetMsg(mywindow->UserPort)) {
  226.             class = NewMessage->Class;
  227.             code = NewMessage->Code;
  228.             ReplyMsg((struct Message *)NewMessage);
  229.             if(class == CLOSEWINDOW) {
  230.                /* say a fond farewell, don't ask fer sure? */
  231.                if(done_flag) {
  232.                   if(timerbit & getbits) {
  233.                      WaitIO((struct IORequest *)&timermsg);
  234.                   }
  235.                   else {
  236.                      cantimer();
  237.                   }
  238.                   SetWindowTitles(mywindow,"",(char *) -1L);
  239.                   /* Need this to cancel out the clrbusy in done() */
  240.                   setbusy();
  241.                   done(1);
  242.                }
  243.             }
  244.          }
  245.       }
  246.       if(keybit & getbits) {
  247.          WaitIO((struct IORequest *)Con_Read);
  248.          ch = ichar;
  249.          Con_Read->io_Data = (APTR)&ichar;
  250.          Con_Read->io_Command = CMD_READ;
  251.          Con_Read->io_Length = 1;
  252.          SendIO((struct IORequest *)Con_Read);
  253.          if(ch == wchar) {
  254.             ioport(cport);
  255.             cursor_on();
  256.             /* could have a timerbit set here.
  257.             */
  258.             if(timerbit & getbits) {
  259.                WaitIO((struct IORequest *)&timermsg);
  260.             }
  261.             else {
  262.                cantimer();
  263.             }
  264.             return;
  265.          }
  266.          if(ch == '\033') {
  267.             ttputs("do_idle\n");
  268.          }
  269.       }
  270.       if(portbit & getbits) {
  271. port_loop:
  272.          while(CURBUF = (struct regd *)GetMsg(my_port)) {
  273.             while(cpyline(0)) {
  274. logit:
  275.                ttputs(port->line);
  276.                p->flags setbit p_give;
  277.                if(iscon(port->line)) {
  278.                   if(timerbit & getbits) {
  279.                      WaitIO((struct IORequest *)&timermsg);
  280.                   }
  281.                   else {
  282.                      cantimer();
  283.                   }
  284.                   ioport(devtnc);
  285.                   return;
  286.                }
  287.             }
  288.          }
  289.       }
  290.       /* This code is deliberately placed last. If a timer bit occurs
  291.          at the same time as a character arrives from the serial port
  292.          then this code will hang the serial port up because afwd()
  293.          tries to use the port again without clearing the existing char.
  294.          So workaround it. Putting the timer code here guarantees that
  295.          even if the ser char did occur it will be handled first and the
  296.          ser char code handles the problem of returning from this routine
  297.          with a timer bit set.
  298.       */
  299.       if(timerbit & getbits) {
  300.          WaitIO((struct IORequest *)&timermsg);
  301.          /* call the forwarding routine */
  302.          curtim();
  303.          curmin = 10 * (l_time[2] - '0') + (l_time[3] - '0');
  304.          afwd(curmin);
  305.          curmon = 10 * (l_date[2] - '0') + (l_date[3] - '0');
  306.  
  307.          if (s_param & s_log_on) if (curmon isnt log_mon) chglog();
  308.  
  309.          settimer(60);
  310.       }
  311.    }
  312. }
  313. /* replace getdat from mbutil to reduce busy waits */
  314. /* IMPLEMENTATION BUG. In the original getdat it busy-idles and
  315.    if the port is transparent and DCD goes off while the port is
  316.    not idle, then it forces the mode to discon and then returns(true).
  317.    This code can only do this properly IF it can wait for DCD to go
  318.    off. I haven't even tried to implement this yet and not sure if it
  319.    can be done properly. I assume that there's a way to Wait() for a
  320.    DCD event but haven't checked it out
  321. */
  322. char *cp;
  323. getdat()
  324. {
  325.  
  326.    register char ch;
  327.    register PORTS *p;
  328.    register struct regd *rp;
  329.    int eflag;
  330.    int curmin;
  331.    ULONG class,waitbits;
  332.    USHORT code;
  333.  
  334.    p = port;
  335.    cp = p->line;
  336.    /* Is a timeout timer required? */
  337.    curmin = 0;
  338.    if(p->flags & p_dotmr) {
  339.       if((p->mode & idle) && (p->dev == p_tnc))
  340.          curmin = 2;
  341.       else
  342.          curmin = p->ctime;
  343.    }
  344.    if(curmin)settimer(curmin);   /* set timeout timer if required */
  345.    p->flags setbit p_dotmr;
  346.  
  347.    if(p == cport) {
  348.       waitbits = windbit | timerbit | keybit;
  349.    }
  350.    else {
  351.       waitbits = windbit | portbit | timerbit | keybit;
  352.       if(cpyline(0))goto cpyin;
  353.    }
  354.    while(1)  {
  355.       /* See if there's already a message waiting for us */
  356.       if(waitbits & portbit) {
  357.          if(CURBUF = (struct regd *)GetMsg(my_port)) {
  358.             goto port_check;
  359.          }
  360.       }
  361.       getbits = Wait(waitbits);
  362.       if(windbit & getbits) {
  363.          while(NewMessage =
  364.                 (struct IntuiMessage *) GetMsg(mywindow->UserPort)) {
  365.             class = NewMessage->Class;
  366.             code = NewMessage->Code;
  367.             ReplyMsg((struct Message *)NewMessage);
  368.             if(class == CLOSEWINDOW) {
  369.                /* say a fond farewell, don't ask fer sure? */
  370.                if(done_flag) {
  371.                   if(timerbit & getbits) {
  372.                      WaitIO((struct IORequest *)&timermsg);
  373.                   }
  374.                   else {
  375.                      cantimer();
  376.                   }
  377.                   SetWindowTitles(mywindow,"",(char *) -1L);
  378.                   done(1);
  379.                }
  380.             }
  381.          }
  382.       }
  383.       if(keybit & getbits) {
  384.          WaitIO((struct IORequest *)Con_Read);
  385.          ch = ichar;
  386.          Con_Read->io_Data = (APTR)&ichar;
  387.          Con_Read->io_Command = CMD_READ;
  388.          Con_Read->io_Length = 1;
  389.          SendIO((struct IORequest *)Con_Read);
  390.          if(ch == '\033') {
  391.             if(p == cport)ttputs("getdatCON\n");
  392.             else          ttputs("getdatTNC\n");
  393.          }
  394.          eflag = 0;
  395.          if(p != cport) {
  396.             if(ch == achar) {
  397.                p->mode = forced;
  398.                eflag = 1;
  399.             }
  400.             if(ch == tchar) {
  401.                p->flags setbit p_opreq;
  402.                eflag = 1;
  403.             }
  404.          }
  405.          else {
  406.             if(charf(ch)) {
  407.                eflag = 1;
  408.             }
  409.          }
  410.          /* If any of the previous three if statements want to
  411.             exit then check that the timer is off and then get out
  412.          */
  413.          if(eflag) {
  414.             if(timerbit & getbits) {
  415.                WaitIO((struct IORequest *)&timermsg);
  416.             }
  417.             else {
  418.                if(curmin)cantimer();
  419.             }
  420.             return(true);
  421.          }
  422.       }
  423.       if(portbit & getbits) {
  424.          while((CURBUF = (struct regd *)GetMsg(my_port)) != 0L) {
  425.             if(optflags[4])interflag = 1;
  426. port_check:
  427.             while(cpyline(0)) {
  428. cpyin:
  429.                ttputs(p->line);
  430.                if(timerbit & getbits) {
  431.                   WaitIO((struct IORequest *)&timermsg);
  432.                }
  433.                else {
  434.                   if(curmin)cantimer();
  435.                }
  436.                if(!(p->flags & p_trans)) {
  437.                   if(isdis(p->line)) {
  438.                      if(!(p->mode & idle))p->mode = discon;
  439.                      return (true);
  440.                   }
  441.                   if(isretry(p->line)) {
  442.                      return (false);
  443.                   }
  444.                   if(isreq(p->line)) {
  445.                      p->flags setbit p_req;
  446.                      pcall(p->rcall,p->line+20);
  447.                      p->flags clrbit p_dotmr;
  448.                      return (false);
  449.                   }
  450.                }
  451.                return (true);
  452.             }
  453.          }
  454.       }
  455.       if(timerbit & getbits) {
  456.          WaitIO((struct IORequest *)&timermsg);
  457.          *cp = 0;
  458.          if(!(p->mode & idle))p->mode = timeout;
  459.          return (true);
  460.       }
  461.    }
  462. }
  463. charf(s)
  464. unsigned char s;
  465. {
  466.    register unsigned char ch;
  467.    PORTS *p;
  468.    p = port;
  469.    ch = s;
  470.    /* Ignore characters with high order bit set...they tie up the TNC */
  471.    if(ch > 0177)return(0);
  472.    *cp = ch;
  473.    if((cp == p->line + linelen - 2) || (ch == '\r')) {
  474.       if(ch == '\r')*cp = '\n';
  475.       *++cp = 0;
  476.       if(p->dev == p_tnc)ttputs(p->line);
  477.       if(p->flags & p_echo)ttputc('\n');
  478.       return(1);
  479.    }
  480.    switch(*cp) {
  481.    default:
  482.       if (p->flags & p_echo) ttputc(*cp);
  483.       cp++;
  484.       break;
  485.    case '\b':
  486.       if(cp > p->line) {
  487.          cp--;
  488.          if(p->flags & p_echo) ttputs("\b \b");
  489.       }
  490.       break;
  491.  
  492.    case '\n':
  493.       if(cp is p->line) {
  494.          *cp = '\0';
  495.          return(1);
  496.       }
  497.       break;
  498.    case '\0' :    /* Ignore most ctl char */
  499.    case ctl_c:    /* Ignore most ctl char */
  500.    case ctl_v:    /* Ignore most ctl char */
  501.    case '\033':
  502.       break;
  503.    }
  504.    return(0);
  505. }
  506.  
  507. /* I am not sure yet what waitcmd has to do anymore because the Host
  508.    mode doesn't return "cmd:" to this process.
  509. */
  510. waitcmd()
  511. {
  512. }
  513.  
  514. /* Remove the busy-wait from term() */
  515. term(s)
  516. PORTS *s;
  517. {
  518.    register char ch,*cp;
  519.    register struct regd *rp;
  520.    register PORTS *m;
  521.    ULONG class,waitbits;
  522.    USHORT code;
  523.    byte ec;
  524.  
  525.    cp = &tmpstr[0];
  526.    m = cport;
  527.    m->flags clrbit p_give;
  528.    ec = s->ec;
  529.    s->ec = true;
  530.    ioport(m);
  531.    waitbits = windbit | portbit | keybit;
  532.    while(cpyline(1))ttputs(port->line);
  533.    while(1)  {
  534.       getbits = Wait(waitbits);
  535.       if(windbit & getbits) {
  536.          while(NewMessage =
  537.                   (struct IntuiMessage *) GetMsg(mywindow->UserPort)) {
  538.             class = NewMessage->Class;
  539.             code = NewMessage->Code;
  540.             ReplyMsg((struct Message *)NewMessage);
  541.             if(class == CLOSEWINDOW) {
  542.                /* say a fond farewell, don't ask fer sure? */
  543.                if(done_flag) {
  544.                   SetWindowTitles(mywindow,"",(char *) -1L);
  545.                   done(1);
  546.                }
  547.             }
  548.          }
  549.       }
  550.       if(keybit & getbits) {
  551.          WaitIO((struct IORequest *)Con_Read);
  552.          ch = ichar;
  553.          Con_Read->io_Data = (APTR)&ichar;
  554.          Con_Read->io_Command = CMD_READ;
  555.          Con_Read->io_Length = 1;
  556.          SendIO((struct IORequest *)Con_Read);
  557.          if(ch == rchar) {
  558.             m->flags setbit p_give;
  559.             s->ec = ec;
  560.             return;
  561.          }
  562.          if(ch == 010) {
  563.             if(cp > &tmpstr[0]) {
  564.                cp--;
  565.                ttputs("\b \b");
  566.             }
  567.          }
  568.          else {
  569.             *cp = ch;
  570.             if(ch == '\r') {
  571.                ttputc('\n');
  572.                if(tmpstr[0] != '!') {
  573.                   *cp++ = '\r';
  574.                   *cp = 0;
  575.                   senddata(&tmpstr[0]);
  576.                }
  577.                else {
  578.                   *cp = 0;
  579.                   sendcommand(&tmpstr[1]);
  580.                }
  581.                cp = &tmpstr[0];
  582.             }
  583.             else {
  584.                cp++;
  585.                ttputc(ch);
  586.             }
  587.          }
  588.       }
  589.       if(portbit & getbits) {
  590.          while(CURBUF = (struct regd *)GetMsg(my_port)) {
  591.             while(cpyline(1)) {
  592.                ttputs(port->line);
  593.             }
  594.          }
  595.       }
  596.    }
  597. }
  598.  
  599.  
  600.  
  601. /* Replace the pause routine so that it can be used with TNC as well
  602.    as the console. If routine times out after 2 minutes then it will
  603.    return 'Q'.
  604.    The test for optflags[2] allows the SYSOP to specify whether the system
  605.    will pause after 20 lines of output to the user.
  606. */
  607. pause()
  608. {
  609.  
  610.    register struct regd *rp;
  611.    register char ch;
  612.    ULONG class,waitbits;
  613.    USHORT code;
  614.  
  615.    /* If remote user has interrupted, then return a 'Q' anyway */
  616.    if((port != cport) && interflag)return('Q');
  617.    if(!optflags[2] && ((port->mode != local) || (pt_flag)))return(' ');
  618.  
  619.    prtx(pausemsg);
  620.    if(port->mode != local)outchar('\n');
  621.    settimer(120);   /* set timeout timer  */
  622.    waitbits = windbit | portbit | timerbit | keybit;
  623.    if(cpyline(0))goto cpyout;
  624.    while(1)  {
  625.       getbits = Wait(waitbits);
  626.       if(windbit & getbits) {
  627.          while(NewMessage =
  628.                    (struct IntuiMessage *) GetMsg(mywindow->UserPort)) {
  629.             class = NewMessage->Class;
  630.             code = NewMessage->Code;
  631.             ReplyMsg((struct Message *)NewMessage);
  632.             if(class == CLOSEWINDOW) {
  633.                /* say a fond farewell, don't ask fer sure? */
  634.                if(done_flag) {
  635.                   if(timerbit & getbits) {
  636.                      WaitIO((struct IORequest *)&timermsg);
  637.                   }
  638.                   else {
  639.                      cantimer();
  640.                   }
  641.                   SetWindowTitles(mywindow,"",(char *) -1L);
  642.                   done(1);
  643.                }
  644.             }
  645.          }
  646.       }
  647.       if(keybit & getbits) {
  648.          WaitIO((struct IORequest *)Con_Read);
  649.          ch = toupper(ichar);
  650.          Con_Read->io_Data = (APTR)&ichar;
  651.          Con_Read->io_Command = CMD_READ;
  652.          Con_Read->io_Length = 1;
  653.          SendIO((struct IORequest *)Con_Read);
  654.          if(timerbit & getbits) {
  655.             WaitIO((struct IORequest *)&timermsg);
  656.          }
  657.          else {
  658.             cantimer();
  659.          }
  660.          outchar('\n');
  661.          return(ch);
  662.       }
  663.       if(portbit & getbits) {
  664.          while(CURBUF = (struct regd *)GetMsg(my_port)) {
  665.             if(cpyline(0)) {
  666. cpyout:
  667.                ttputs(port->line);
  668.                /* portbit has been handled but timerbit could be set */
  669.                if(timerbit & getbits) {
  670.                   WaitIO((struct IORequest *)&timermsg);
  671.                }
  672.                else {
  673.                   cantimer();
  674.                }
  675.                return(port->line[0]);
  676.             }
  677.          }
  678.       }
  679.       /* check for timeout */
  680.       if(timerbit & getbits) {
  681.          WaitIO((struct IORequest *)&timermsg);
  682.          return('Q');
  683.       }
  684.    }
  685. }
  686. /*  if (instat()) if (getdat()) if (isdis(port->line))  */
  687. /* Replace a piece of the chkdis code in mbfwd.
  688.    If there's received data, then if it is a disconnected message
  689.    (ought to be sure of disconnect status - it could be data!)
  690.    or if it is an abort command, then let them know .
  691. */
  692. disport()
  693. {
  694.    register struct regd *rp;
  695.    *port->line = 0;
  696.    if(cpyline(0))goto gotone;
  697.    while(CURBUF = (struct regd *)GetMsg(my_port)) {
  698.       while(cpyline(0)) {
  699. gotone:
  700.          if(isdis(port->line) || ((toupper(*port->line) == 'A') &&
  701.                                   (rp->mp.msgsize == 2))) {
  702.             ttputs(port->line);
  703.             return(true);
  704.          }
  705.          return(false);
  706.       }
  707.    }
  708.    return(false);
  709. }
  710.  
  711.  
  712. /* Copy data from the serial port to port->line.
  713.    If flag is set then return an incomplete line, otherwise wait for
  714.    a CR before sending a line.
  715. */
  716. cpyline(flag)
  717. {
  718.    register struct regd *rp;
  719.    register unsigned char *cp,*kp;
  720.    register short i;
  721.  
  722.    if((rp = CURBUF) == 0)return(0);
  723.    if((kp = B_FROM) == 0)
  724.       kp = &rp->mp.msg[0];
  725.    if((cp = B_TO) == 0)
  726.       cp = (unsigned char *) port->line;
  727.    i = rp->mp.msgsize;
  728.  
  729.    if(i == 0) {
  730.       *cp = 0;
  731.       ReplyMsg((struct Message *)CURBUF);
  732.       CURBUF = 0;
  733.       B_FROM = 0;
  734.       return(0);
  735.    }
  736.    do {
  737.       if(tapr_flag)
  738.          *cp = *kp++ & 0177;
  739.       else
  740.          *cp = *kp++;
  741.       if(*cp == '\r') {
  742.          if((rp->mp.msgsize = (i-1)) == 0 ){
  743. out:
  744.             ReplyMsg((struct Message *)CURBUF);
  745.             CURBUF = 0;
  746.             B_TO = B_FROM = 0;
  747.             *cp++ = '\n';
  748.             *cp = 0;
  749.             return(1);
  750.          }
  751.          B_FROM = kp;
  752.          B_TO = 0;
  753.          *cp++ = '\n';
  754.          *cp = 0;
  755.          return(1);
  756.       }
  757.       cp++;
  758.    } while(--i);
  759.    if(rp->mp.cmd != 'D')goto out;
  760.    *cp = 0;
  761.    ReplyMsg((struct Message *)CURBUF);
  762.    CURBUF = 0;
  763.    B_FROM = 0;
  764. /* If flag is set then return a partial data packet.
  765.    Otherwise say we're not done yet and let them give us more
  766. */
  767.    if(flag) {
  768.       B_TO = 0;
  769.       return(1);
  770.    }
  771.    B_TO = cp;
  772.    return(0);
  773. }
  774. fromhex(s)
  775. char *s;
  776. {
  777.    register int i,j;
  778.    register char *p;
  779.    p = s;
  780.    i = 0;
  781.  
  782.    if((i = hex(*p++)) < 0)return(-1);
  783.    j = hex(*p);
  784.    if(j < 0)return(-1);
  785.    i <<= 4;
  786.    i |= j;
  787.    return(i);
  788. }
  789.